<?php
/*
本插件禁止删除，为本框架核心插件之一。
本插件提供框架版本信息，框架升级，远程POST网页，就是如果某一个服务器的IP被拉入黑名单，可以使用setagent()，让拉取服务的功能转移到其他主机上面。
*/

namespace core;

class Application extends \Applications
{
    private $gitsrc = "https://gitee.com/bgcls/webhook/";
    private $prifx="/core";
    private $remote_view_pass=false;#"123456";
    //private $config=array();
    /**
     * 入口函数
     */
    function build()
    {
        if (!file_exists(__ROOT__.'install.lock')) {
            $this
                ->route("/core/test", "app_install_test")
                ->default("app_install");
            return;
        }
        //$this->config=$this->parse_ini_file('app.ini',false);
        $this->prifx=$this->config["prifx"]??$this->prifx;
        
        $this->remote_view_pass=$this->config["remote_pass"]??$this->remote_view_pass;

        $this
            ->route($this->prifx."/show", "getversion")
            ->route($this->prifx."/agent", "agent")
            ->route($this->prifx."/agent/check", "agentstatus")
            ->route($this->prifx."/install", "install")
            ->route($this->prifx."/pluginmanger", "pluginmanger")
            ->route($this->prifx."/update", "update")
            ->route($this->prifx, "index_root")
            ->route($this->prifx."/", "index_root")
			->route($this->prifx."/db","db_test")
            ->route("/core/dns", 'generate_dns')

            ->default("action_other")
            ->debug = false;
    }
    function agentstatus()
    {
        $data["code"] = 200;
        $this->write($data);
    }
	



    function generate_dns()
    {
        $path = __ROOT__.'plugin/';
        if($_GET["i"]=="all"){
            
            $data = [];
            $files = scandir($path, 1);
            $ip = gethostbyname($_SERVER['HTTP_HOST']);
            foreach ($files as $v) {
                if (substr($v, -4) !== ".php") {
                    continue;
                }
                if ($v == "version.php") {
                    continue;
                }
                if (!is_file($path . $v)) continue;
                $data[] =  $ip. " ".basename($v, ".php") ;
            }
            $this->write(join("\r\n", $data));
        }else if($_GET["i"]==""){
            $v=file_get_contents(__ROOT__.$this->prifx.$this->remote_view_pass.".ini");
            $ip = gethostbyname($_SERVER['HTTP_HOST']);
            if(is_file($path . $v)){
                $this->write($ip. " ".basename($v, ".php")."\r\n");
            }else{
                $this->write("应用不存在");
            }
            //$this->write("操作错误");
        }else {
            $v=$_GET["i"].".php";
            $ip = gethostbyname($_SERVER['HTTP_HOST']);
            if(is_file($path . $v)){
                $this->write($ip. " ".basename($v, ".php")."\r\n");
            }else{
                $this->write("应用不存在");
            }
        }
        
    }
    function app_install_test()
    {
        $this->write("1");
    }
    /*首次安装框架运行 */
    function app_install()
    {
        //启用实时输出功能
        ob_end_clean();
        ob_implicit_flush(1);
        $m = array("apache", "nginx", "iis");
        $filename = array(".htaccess", "nginx.htaccess", "web.config");

        $dir = "raw/master/伪静态规则/";
        //$url=array("");
        $type = get_runtype();
        $this->write("检测服务器类型:" . $m[get_runtype()] . "<br/>");
        $this->write("安装伪静态规则....");
        $try=0;
        while (1) {
            $try++;
            $data = $this->get($this->gitsrc . $dir . $m[get_runtype()] . ".txt");
            if ($data == "") {
                $this->write("[访问gitee失败]");
            }else if (strlen($data)<60 && strpos($data,"rewrite")===false) {//根据相关法律政策,该内容无法显示
                
                //第一次访问会出现这个
            }else{
                break;
            }

            if($try>5){
                $this->write("停止重试");
                return;
            }else{
                $this->write("重试");
            }

        }
        $ret = file_put_contents(__ROOT__."/".$filename[get_runtype()], $data);
        if (!$ret) {
            $this->write("[保存配置文件失败]");
            return;
        }
        $this->write("[成功]<br/>");
        $this->write("检测是否安装成功...");
        $this->url = "/core/test";
        $data = $this->forword();
        var_dump($data);    
        if ($data != "1") {
            $this->write("[失败]<br/>");
            $this->write("伪静态设置失败，请手动设置，规则参考thinkphp或" . $this->gitsrc . $dir);
            return;
        }
        $this->write("[成功]<br/>");
        $this->write("设置当前访问域名为主域名...");
        $ret = file_put_contents(__ROOT__."/install.lock", $this->host);
        if (!$ret) {
            $this->write("[保存配置文件失败]");
            return;
        }
        $this->write("[成功]<br/>");
        $default_config=<<<EOF
remote_pass=123456
prifx=/core
EOF;
        $ret = $this->file_put_contents("app.ini", $default_config);

        $this->write("<br/><br/><a href='{$this->prifx}/'>点我进入框架页面</a>");
    }
    function configure(){
        return array(
            "debug"=>array(false, "bool", "debug模式"),
            "remote_pass"=>array("","string","远程数据代理访问本机框架的密码"),
            "prifx"=>array("/core","string","本机框架入口")
        );
    }
    /**
     * 其他未注册的页面
     */
    function action_other()
    {
        $this->write("404 NOT FOUND ,插件没有提供此页面");
        return;
    }
    /**
     * 插件管理：删除，增加，查看列表，查看日志列表
     */
    function pluginmanger()
    {
        $data["code"] = 200;
        $appname=@$_GET["file"];
        //$data["debug"]=1;
        switch ($_GET["type"]) {
            case "install":
                $tool = new \tool();
                $data = $tool->plugin_install($_POST["data"]);
                // return;
                break;
            case "list":
                $data["data"] = $this->get_all_plugin_info();
                break;
            case "delete":
                $data["data"] = @unlink(__ROOT__."plugin/" . $appname . ".php");
                break;
            case "log":
                //$data["file"]=__ROOT__."data/" . $appname . "/logs.txt";
                $data["data"] = @file_get_contents(__ROOT__."data/" . $appname . "/logs.txt");
                break;
            case "deletelog":
                $data["data"] = @unlink(__ROOT__."data/" .$appname . "/logs.txt");
                break;
            case "getconfig":
                $app=\tool::load_plugin(__ROOT__."plugin/".$appname.".php");
                $content=$app->parse_ini_file("app.ini");
                //$content = json_decode(@file_get_contents(__ROOT__."data/" . $app . "/app.ini"),true);
                $cfg=[];
                foreach ($content as $key => $value) {
                    $cfg[$key]=array($value);
                }
                //print_r(array($app->configure(),$cfg));
                $data["data"]=array_replace_recursive($app->configure(),$cfg);
                break;
            case "saveconfig":
                $app=\tool::load_plugin(__ROOT__."plugin/".$appname.".php");
                $content=$_POST["data"];
                $data["data"]=$this->save_ini($app,$content);
                break;
            case "switchdebug":
                $app=\tool::load_plugin(__ROOT__."plugin/".$appname.".php");
                $content=$app->parse_ini_file("app.ini");
                $content["debug"]=!($content["debug"]);
                $data["data"]=$this->save_ini($app,$content);
                break;
            default:
                $data["code"] = 404;
                $data["msg"] = "找不到页面";
        }
        $this->write($data);
    }
    private function save_ini($app,$conf){
        $cfg=[];
        foreach ($conf as $key => $value) {
            $cfg[]=$key."=".$value;
        }
        return $app->file_put_contents("app.ini",join("\r\n",$cfg));
    }
    /**
     * 获取所有已安装插件的信息。
     */
    private function get_all_plugin_info()
    {
        $path = __ROOT__.'plugin/';
        $data = [];
        $files = scandir($path, 1);
        $data[] = $this->getinfo();
        $data[0]["file"]=basename($data[0]["file"], ".php");
        foreach ($files as $v) {
            if (substr($v, -4) !== ".php") {
                continue;
            }
            if ($v == "version.php") {
                continue;
            }
            if (is_file($path . $v)) {
                try {
                    $app = \tool::load_plugin($path . $v);
                    if ($app === false) continue;
                    $info = $app->getinfo();
                } catch (\Exception $e) {
                    $info = parent::getinfo();
                    $info["content"] = "插件加载出错！" . $e;
                }
                $info["file"] = basename($v, ".php");
                $data[] = $info;
            }
        }
        return $data;
    }

    function getinfo()
    {
        return array("author" => "WANYL", "file" => 'version.php', "title" => "核心插件", "content" => "负责框架管理部分", "help_url" => $this->gitsrc, "icon" => "", "version" => VERSION);
    }

    /**
     * 远程代理
     */
    function agent()
    {
        if($this->remote_view_pass===false||$this->remote_view_pass=='')return;
        if ($_GET["sign"] != $this->remote_view_pass) return;
        $data = json_decode($this->post, true); //获取参数列表
        $this->write(curl_post_real_full(...$data));
        
    }
    /**
     * 插件主页面
     */
    function getversion()
    {
        $host = $this->host;
        $version = VERSION;
        $gitsrc = $this->gitsrc;
        $phpversion = PHP_VERSION;
        $proxyurl="http://{$this->host}{$this->prifx}/agent?sign={$this->remote_view_pass}";
        if($this->remote_view_pass===false||$this->remote_view_pass==''){
            $proxyurl="服务未开启.";
        }
        $data = <<<EOF
        <style type = "text/css">
        #url_address{
            border-width:0px;outline:none;
            border-bottom:1px solid #eee;
            width:280px;
        }
        #url_address:focus{
            border-bottom:1px solid #456;
        }
        </style>
 框架制作者:WANYL<br/>
 QQ:2557054528<br/>
 框架版本:$version<br/>
 PHP版本:$phpversion<br/>
 当前访问域名:$host<br/>
 proxy代理链接地址：$proxyurl<br/>
 框架开源地址:<a href='$gitsrc'>$gitsrc</a><br/>
 插件链接:<input  id="url_address" autocomplete='off' type='text' name='url'><input type='file' id='openexplorer'><a onclick='$("#openexplorer").click()'>选择本地文件</a><a onclick='install()'>安装插件</a><br/>
    <script>
        $("#openexplorer").hide();
        $('#openexplorer').change(function () {
            var file = this.files[0];
            var fr = new FileReader();
            fr.readAsDataURL(file);
            fr.onload = function(){
                content=fr.result.split(';base64,')[1];
                $('#url_address').val("base64://"+content);
            }
        })
        function install(){
            $.post("{$this->prifx}/pluginmanger?type=install",{data:$("#url_address").val()},function(data){
                data=JSON.parse(data);
                alert(data["msg"]);
                if(data["code"]==200)location.reload();
            })
        }
    </script>
EOF;
        $newversion = $this->should_update(true);
        if ($newversion != "") {
            if ($this->should_update()) {
                $data .= "最新版本:$newversion";
                $data .= "<a href='{$this->prifx}/update'>立即更新</a>";
            } else {
                $data .= "最新版本:$newversion [无需更新]";
            }
        }
        $this->write($data);
        return;
    }
    private function should_update($retv = false)
    {
        static $content;

        if ($content == null) $content = $this->get($this->gitsrc . "raw/master/core.php");

        $con_array = explode("\n", $content);
        $newstr = str_replace("define(", "[", $con_array[1]);
        $newstr = str_replace(")", "]", $newstr);
        $newstr = trim($newstr, ";");
        $news = json_decode($newstr, true);
        $newversion = $news[1];
        if ($retv) return $newversion;
        return $this->fvc($newversion) > $this->fvc(VERSION);
    }
    function update()
    {
        if (!$this->should_update()) {
            echo "框架已经是最新版本!<a href='{$this->prifx}'>返回到信息页面</a>";
            exit;
        }
        $newversion = $this->should_update(true);
        $version = VERSION;
        $content = $this->get($this->gitsrc . "raw/master/map");
        $data = json_decode($content, true);
        $filemap = $data["file"];
        for ($i = 0; $i < count($filemap); $i++) {
            $d = $filemap[$i];
            $dir = dirname($d);
            if (!is_dir($dir)) mkdir($dir, '0777', true);
            $content = $this->get($this->gitsrc . "raw/master/" . $d);
            file_put_contents(__ROOT__.$d, $content);
        }
        $this->write("从完成{$version}->{$newversion}升级完成.<br/><a href='{$this->prifx}'>返回到信息页面</a>");
    }
    private function fvc(string $str)
    { // function_version_calc     计算版本
        $v = explode('.', $str);
        for ($i = 1; $i < 4; $i++) if ($v[$i] == "") $v[$i] = "0";
        $k = 0;
        for ($i = count($v) - 1, $m = 0; $i >= 0; $i--, $m++) {
            $k += pow(10, $m * 3) * $v[$i];
        }
        return $k;
    }



    function index_root()
    {
        $data = <<<EOF
         <html>
         <script src="https://s3.pstatp.com/cdn/expire-1-M/jquery/3.3.1/jquery.min.js"></script>
         <script>
            png_exist="";
         </script>
         <style>
            body {
                background: whitesmoke;
            }
            /*定义滚动条高宽及背景 高宽分别对应横竖滚动条的尺寸*/
          ::-webkit-scrollbar{
            width: 7px;
            height: 7px;
            background-color: #F5F5F5;
          }
        
          /*定义滚动条轨道 内阴影+圆角*/
          ::-webkit-scrollbar-track {
            box-shadow: inset 0 0 6px rgba(0, 0, 0, 0.3);
            -webkit-box-shadow: inset 0 0 6px rgba(0, 0, 0, 0.3);
            border-radius: 10px;
            background-color: #F5F5F5;
          }
        
          /*定义滑块 内阴影+圆角*/
          ::-webkit-scrollbar-thumb{
            border-radius: 10px;
            box-shadow: inset 0 0 6px rgba(0, 0, 0, .1);
            -webkit-box-shadow: inset 0 0 6px rgba(0, 0, 0, .1);
            background-color: #c8c8c8;
          }
        
            html,
            body,
            * {
                margin: 0px;
                padding: 0px;
                font-variant: 500px;
        
                font-family: "Microsoft YaHei", 微软雅黑, "MicrosoftJhengHei", 华文细黑, STHeiti, MingLiu
            }
        
            .navigation-bar {
                height: 60px;
                background: #fff;
                border: 1px solid #ddd;
            }
        
            .navigation-bar-content {
                margin: 0px auto;
                width: 1000px;
                height: 100%;
                background: #fff;
                display: table;
                letter-spacing: 5px;
            }
        
            .navigation-bar-content>* {
                display: table-cell;
                vertical-align: middle;
                width:100px;
                text-align:center
            }
        
            .body-content {
                background: #fff;
        
                /*position:absolute;*/
                border: 1px solid #ddd;
                margin: 20px auto;
                
                padding: 50px;
                padding-right: 10px;
                width: 1000px;
                height: 600px;
                display: flex;
            }
        
            span.delete {
                background: url("");
                padding: 0px 7px;
                
                cursor: pointer;
            }
            ul{
                list-style-type: none;
                padding-right:40px; 
            }
            li{
                margin-top:20px;
            }
            a{
                color:#56c9fd;
                text-decoration:none;
            }
            a:visited{
                color:#56c9fd;
            }
            a[href],a[onclick]{
                cursor: pointer;
            }
            a[href]:hover,a[onclick]:hover{
                text-decoration:underline;
            }
            .navigation-bar-content>a.selected{
                background:#ccc;
                color:#fff;
            }
            .navigation-bar-content>a[onclick]:not(.selected):hover{
                background:#eee;
            }
         </style>
        
         <body onselectstart="return false;">
        
            <div class='navigation-bar'>
                <div class='navigation-bar-content'>
                    
                    <a onclick=''>插件管理</a>
                    <a onclick=''>框架管理</a>
                    <a onclick=''>其他信息</a>
                    <a>&#12288;&#12288;&#12288;&#12288;&#12288;&#12288;&#12288;&#12288;&#12288;&#12288;</a>
                    <a>&#12288;&#12288;&#12288;&#12288;&#12288;&#12288;&#12288;</a>
                    <a>&#12288;&#12288;&#12288;&#12288;&#12288;&#12288;&#12288;</a>
                    <a>&#12288;&#12288;&#12288;&#12288;&#12288;&#12288;&#12288;</a>
                </div>
            </div>
            <div class='body-content'>
                
                <ul style="width:100%;overflow-y:auto;" id='app_list' class='page'>
                    
                </ul>
                <ul style="width:100%;overflow-y:auto;display:none;font-size:14px;" class='page'>
                    <div id='page_info' style='width:600px;height:400px;color:ff9800'>
                        </div>
                </ul>
                <ul style="width:100%;overflow-y:auto;display:none;font-size:14px;" class='page'>
                    SSL证书生成：<br/>
                    第1步.<a href='https://csr.chinassl.net/generator-csr.html'>https://csr.chinassl.net/generator-csr.html</a><br/>
                    第2步.<a href='https://csr.chinassl.net/free-ssl.html'>https://csr.chinassl.net/free-ssl.html</a>
                </ul>
                
            </div>
            <script>
                $(function(){
                    var btn=$(".navigation-bar-content>a");
                    var page=$(".page");
                    var m=function attach(){
                        var btn=$(".navigation-bar-content>a");
                        var index=btn.index(this);
                        var page=$(".page");
                        for(var i=0;i<page.length;i++){
                            
                            if(i==index){
                                $(btn[i]).addClass("selected");
                                $(page[i]).show();
                            }else{
                                $(btn[i]).removeClass("selected");
                                
                            $(page[i]).hide();}
                        }
                    }
                    for(var i=0;i<btn.length&&i<page.length;i++){
                        $(btn[i]).click(m);
                    }
                    $(btn[0]).click();
                });
                $.get("{$this->prifx}/show",function(data){
                    $("#page_info").html(data);
                })
                $.get("{$this->prifx}/pluginmanger?type=list", function (data) {
                    data = JSON.parse(data);
                    data=data["data"];
                    $("#app_list").html();
                    var __html = `
                    
                    <li>
                        <table style='font-size:12px;width:100%;'>
                            <tr>
                                <td rowspan="3" style='width:80px;'><img style='width:32px;height:32px;padding:16px;' src='{icon}'/></td>
                                <td><a style='font-weight: 600;'>{title}</a><a style='color:#aaa;margin-left:20px'>{version}</a></td>
                                <td style='width:50px;text-align:right'><span class='delete' data='{file}'></span></td>
                            </tr>
                            <tr>
                                <td style='color:#aaa;'>{content}</td>
                            </tr>
                            <tr>
                                <td>
                                    <a>详细信息</a> &#12288;
                                    <a onclick='log_clean("{file}")'>清理日志</a>&#12288;
                                    <a onclick='log_show("{file}")'>查看日志</a>&#12288;
                                    <a onclick='switchdebug("{file}")'>调试模式</a>
                                </td><td style='text-align:right'><a href='{help_url}' target="_blank" >{help_url}</a></td>
                            </tr>
                        </table>
                    </li>
                    `;
        
                    var out=[];
                    var def={"icon":png_exist,"title":"匿名插件","version":"1.0.0.0","content":"作者没有留下任何内容","help_url":"","file":""}
                    for(var i=0;i<data.length;i++){
                        var line= data[i];
                        var html=__html;
                        
                        for (var  key in def) {
                            if(line[key]==""||line[key]==null)line[key]=def[key];
                            html=html.replace(new RegExp("{"+key+"}", "gm"),line[key]);
                        }
                        out.push(html);
                    }
                    $("#app_list").append(out.join("<br/><hr/>"));
                    $("#app_list").append("<br/><center><a style='color:#aaa'>共"+data.length+"个插件</a></center>");
                    $(".delete:nth(0)").hide();
                    $(".delete").click(function(){
                        var file=$(this).attr("data");
                        if(!confirm("你确认删除"+file+"这个插件?"))return;
                        $.get("{$this->prifx}/pluginmanger?type=delete&file="+file,function(data){
                        data=JSON.parse(data);
                        if(data["code"]==200){
                            alert("删除"+(data["data"]?"成功":"失败"));
                            location.reload();
                        }else{
                            alert("网络链接失败");
                        }
                })
                    })
                });
                function log_clean(app){
                    $.get("{$this->prifx}/pluginmanger?type=deletelog&file="+app,function(data){
                        alert("清理成功");
                    });
                }
                function log_show(app){
                    $.get("{$this->prifx}/pluginmanger?type=log&file="+app,function(data){
                        var idm=window.open("","_blank","height=600,width=800");
                        data=JSON.parse(data);
                        idm.document.write("<textarea style='width:100%;height:100%'>");
                        idm.document.write(data['data']);
                        idm.document.write("</textarea>");return;
                        idm.onload=function()
                        {
                            idm.document.body.innerHTML="<textarea>"+data['data']+"</textarea>";
                        }
                        //alert("清理成功");
                    });
                }
                function switchdebug(app){
                    $.get("{$this->prifx}/pluginmanger?type=switchdebug&file="+app,function(data){
                        alert("切换成功")
                    });
                }
            </script>
         </body>
        
         </html>

EOF;
        $this->write($data);
    }
}
